'use strict';

var times = require('../times');

var success = {
  name: 'success'
  , label: 'Weekly success'
  , pluginType: 'report'
};

function init() {
  return success;
}

module.exports = init;

success.html = function html(client) {
  var translate = client.translate;
  var ret =
     '<h2>' + translate('Weekly Success') + '</h2>'
    + '<div id="success-grid"></div>'
    ;
  return ret;
};

success.css = 
  '#success-placeholder td {'+
  '	border: 1px #ccc solid;'+
  '	margin: 0;'+
  '	padding: 1px;'+
  ' text-align:center;'+
  '}'+
  '#success-placeholder .bad {'+
  '	background-color: #fcc;'+
  '}'+

  '#success-placeholder .good {'+
  '	background-color: #cfc;'+
  '}'+

  '#success-placeholder th:first-child {'+
  '	width: 30%;'+
  '}'+
  '#success-placeholder th {'+
  '	width: 10%;'+
  '}'+
  '#success-placeholder table {'+
  '	width: 100%;'+
  '}'
  ;



success.report = function report_success(datastorage, sorteddaystoshow, options) {
  var Nightscout = window.Nightscout;
  var client = Nightscout.client;
  var translate = client.translate;

  var ss = require('simple-statistics');

  var low = options.targetLow,
    high = options.targetHigh;

  var data = datastorage.allstatsrecords;
    
  var now = Date.now();
  var period = 7 * times.hours(24).msecs;
  var firstDataPoint = data.reduce(function(min, record) {
      return Math.min(min, record.displayTime);
    }, Number.MAX_VALUE);
  if (firstDataPoint < 1390000000000) {
    firstDataPoint = 1390000000000;
  }
  var quarters = Math.floor((Date.now() - firstDataPoint) / period);

  var grid = $('#success-grid');
  grid.empty();
  var table = $('<table/>');

  if (quarters === 0) {
    // insufficent data
    grid.append('<p>'+translate('There is not sufficient data to run this report. Select more days.')+'</p>');
    return;
  }

  var dim = function(n) {
    var a = [];
    for (var i = 0; i < n; i++) {
      a[i]=0;
    }
    return a;
  };
  var sum = function(a) {
    return a.reduce(function(sum,v) {
      return sum+v;
    }, 0);
  };
  var averages = {
    percentLow: 0,
    percentInRange: 0,
    percentHigh: 0,
    standardDeviation: 0,
    lowerQuartile: 0,
    upperQuartile: 0,
    average: 0
  };
  quarters = dim(quarters).map(function(blank, n) {
    var starting = new Date(now - (n+1) * period),
      ending = new Date(now - n * period);
    return {
      starting: starting,
      ending: ending,
      records: data.filter(function(record) {
        return record.displayTime > starting &&  record.displayTime <= ending;
      })
    };
  }).filter(function(quarter) {
    return quarter.records.length > 0;
  }).map(function(quarter, ix, all) {
    var bgValues = quarter.records.map(function(record) {
      return record.sgv;
    });
    quarter.standardDeviation = ss.standard_deviation(bgValues);
    quarter.average = bgValues.length > 0? (sum(bgValues) / bgValues.length): 'N/A';
    quarter.lowerQuartile = ss.quantile(bgValues, 0.25); 
    quarter.upperQuartile = ss.quantile(bgValues, 0.75);
    quarter.numberLow = bgValues.filter(function(bg) {
      return bg < low;
    }).length;
    quarter.numberHigh = bgValues.filter(function(bg) {
      return bg >= high;
    }).length;
    quarter.numberInRange = bgValues.length - (quarter.numberHigh + quarter.numberLow);

    quarter.percentLow = (quarter.numberLow / bgValues.length) * 100;
    quarter.percentInRange = (quarter.numberInRange / bgValues.length) * 100;
    quarter.percentHigh = (quarter.numberHigh / bgValues.length) * 100;

    averages.percentLow += quarter.percentLow / all.length;
    averages.percentInRange += quarter.percentInRange / all.length;
    averages.percentHigh += quarter.percentHigh / all.length;
    averages.lowerQuartile += quarter.lowerQuartile / all.length;
    averages.upperQuartile += quarter.upperQuartile / all.length;
    averages.average += quarter.average / all.length;
    averages.standardDeviation += quarter.standardDeviation / all.length;
    return quarter;
  });

  var lowComparison = function(quarter, averages, field, invert) {
    if (quarter[field] < averages[field] * 0.8) {
      return (invert? 'bad': 'good');
    } else if (quarter[field] > averages[field] * 1.2) {
      return (invert? 'good': 'bad');
    } else {
      return '';
    }
  };

  var lowQuartileEvaluation = function(quarter, averages) {
    if (quarter.lowerQuartile < low) {
      return 'bad';
    } else {
      return lowComparison(quarter, averages, 'lowerQuartile');
    }
  };

  var upperQuartileEvaluation = function(quarter, averages) {
    if (quarter.upperQuartile > high) {
      return 'bad';
    } else {
      return lowComparison(quarter, averages, 'upperQuartile');
    }
  };

  table.append('<thead><tr><th>'+translate('Period')+'</th><th>'+translate('Low')+'</th><th>'+translate('In Range')+'</th><th>'+translate('High')+'</th><th>'+translate('Standard Deviation')+'</th><th>'+translate('Low Quartile')+'</th><th>'+translate('Average')+'</th><th>'+translate('Upper Quartile')+'</th></tr></thead>');
  table.append('<tbody>' + quarters.filter(function(quarter) {
    return quarter.records.length > 0;
  }).map(function(quarter) {
    var INVERT = true;
    return '<tr>' + [
      quarter.starting.toLocaleDateString() + ' - ' + quarter.ending.toLocaleDateString(),
      {
        klass: lowComparison(quarter, averages, 'percentLow'),
        text: Math.round(quarter.percentLow) + '%'
      },
      {
        klass: lowComparison(quarter, averages, 'percentInRange', INVERT),
        text: Math.round(quarter.percentInRange) + '%'
      },
      {
        klass: lowComparison(quarter, averages, 'percentHigh'),
        text: Math.round(quarter.percentHigh) + '%'
      },
      {
        klass: lowComparison(quarter, averages, 'standardDeviation'),
        text: (quarter.standardDeviation > 10? Math.round(quarter.standardDeviation): quarter.standardDeviation.toFixed(1))
      },
      {
        klass: lowQuartileEvaluation(quarter, averages),
        text: quarter.lowerQuartile
      },
      {
        klass: lowComparison(quarter, averages, 'average'),
        text: quarter.average.toFixed(1)
      },
      {
        klass: upperQuartileEvaluation(quarter, averages),
        text: quarter.upperQuartile
      }
    ].map(function(v) {
      if (typeof v === 'object') {
        return '<td class=\"' + v.klass + '\">' + v.text + '</td>';
      } else {
        return '<td>' + v + '</td>';
      }
    }).join('') + '</tr>';
  }).join('') + '</tbody>');
  table.appendTo(grid);

};
